package com.nagornyi.uc.dao.app;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import com.nagornyi.uc.cache.TicketCache;
import com.nagornyi.uc.dao.DAOFacade;
import com.nagornyi.uc.dao.ITicketDAO;
import com.nagornyi.uc.entity.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Nagorny
 *         Date: 22.05.14
 */
public class TicketDAO extends EntityDAO<Ticket> implements ITicketDAO {

    @Override
    protected Ticket createDAOEntity(Entity entity) {
        return new Ticket(entity);
    }

    @Override
    protected String getKind() {
        return "Ticket";
    }

    @Override
    public int getFreeSeatsNumberForTrip(Trip trip) {
        int count = countForQuery(new Query(getKind()).setAncestor(trip.getKey()).
                setFilter(new Query.FilterPredicate("status",
                        Query.FilterOperator.NOT_EQUAL,
                        Ticket.Status.INVALID.idx)));
        return trip.getSeatsNum() - count - TicketCache.getLockedCount(trip.getStringKey());
    }

    @Override
    public List<Ticket> getTicketsForTrip(Trip trip) {
       return getValidTicketsForTrip(trip);
    }

    @Override
    public List<Seat> getUnavailableSeatsForTrip(Trip trip) {
        List<Ticket> tickets = getValidTicketsForTrip(trip);
        List<Seat> seats = new ArrayList<Seat>();
        for(Ticket t: tickets) {
            seats.add(t.getSeat());
        }

        seats.addAll(TicketCache.getLockedSeats(trip.getStringKey()));
        return seats;
    }
    
    private List<Ticket> getValidTicketsForTrip(Trip trip) {
        return get(trip.getKey(),
                new Query.FilterPredicate("status",
                        Query.FilterOperator.NOT_EQUAL,
                        Ticket.Status.INVALID.idx), null, null);
    }

    @Override
    public boolean sameTicketExists(Ticket newTicket) {
        List<Ticket> tickets = get(newTicket.getParentKey(),
                new Query.FilterPredicate("seat",
                        Query.FilterOperator.EQUAL,
                        newTicket.getSeat().getKey()), null, null);



        return !tickets.isEmpty() || TicketCache.sameExists(newTicket);
    }

    @Override
    public List<Ticket> getTicketsByUser(User user) {
        List<Order> orders = DAOFacade.findByParent(Order.class, user.getKey());
        List<Ticket> tickets = new ArrayList<Ticket>();
        for (Order order: orders) {
            tickets.addAll(order.getTickets());
        }
        return tickets;
    }

    @Override
    public void lockTicket(Ticket ticket) {
        TicketCache.lockTicket(ticket);
    }

    @Override
    public Ticket pollLockedTicket(String tripId, String ticketId) {
        return TicketCache.pollLockedTicket(tripId, ticketId);
    }
}
